package cn.microservices.cloud.gateway.service;

import cn.microservices.cloud.gateway.base.enums.AuthEnums;
import cn.microservices.cloud.gateway.entity.JSONResult;
import cn.microservices.cloud.gateway.entity.ResultCode;
import cn.microservices.cloud.gateway.interpector.ip.IpInterceptor;
import cn.microservices.cloud.gateway.util.Md5Util;
import cn.microservices.cloud.gateway.exceptions.BusinessException;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import cn.microservices.cloud.gateway.util.token.Token;

import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;


@Slf4j
@Component
public class AuthServiceImpl implements AuthService {
    @Autowired
    @Qualifier("tokenRedis")
    private RedisTemplate redisTemplate;
    @Autowired
    @Qualifier("redis")
    private RedisTemplate redis;


    @Value("${spring.profiles.active}")
    private String active;

    @Autowired
    private IpInterceptor ipInterceptor;
    //用户Key
    private static final String USER_TOKEN_KEY = "metagross_token:";
    //当前登录用户Key
    private static final String USER_TOKEN_LOGIN_INFO_KEY = "metagross_token:userInfo:";
    // 权限 Key
    private static final String URL_AUTH_KEY = "microservices:url:auth:%s";
    private static final String URL_PERMISSION_KEY = "microservices:url:permission:%s";
    private static final String URL_ROLE_KEY = "microservices:url:role:%s";
    private static final String URL_USER_PERMISSION_KEY = "microservices:url:user:%s";

    /*===================认证过滤====================*/
    // 表示不需要登录，就可以访问资源
    private static final String ANNO = "anno";
    // 表示需要登录认证才能访问资源，一般用于登录接口
    private static final String AUTHC = "authc";
    // 表示必须用户登录后才能访问资源，当登入操作时不做检查
    private static final String USER = "user";

    /*===================授权过滤====================*/
    // perms：例如/a/sys/user/**=perms[user:add:*]，参数可以写多个，多个时必须加上引号，并且参数之间用逗号分割，
    // 例如/a/sys/user/**=perms["user:add:*,user:modify:*"]，当有多个参数时必须每个参数都通过才通过，想当于isPermitedAll()方法。
    private static final String PERMS = "perms";
    // roles：例如/a/sys/user/**=roles[admin],参数可以写多个，多个时必须加上引号，并且参数之间用逗号分割，当有多个参数时，
    // 例如/a/sys/user/**=roles["admin,guest"]，每个参数通过才算通过，相当于hasAllRoles()方法。
    private static final String ROLES = "roles";

    //加盐
    private static String signSalt = "microservices";


    /**
     * 验证token的有效性及是否具备对该url的访问权限，
     * 判定规则参考了shiro的一些设定
     *
     * @return
     */
    @Override
    public Token verifyToken(String url, String token, ServerHttpResponse response) throws BusinessException {

        Object tokenObj = redisTemplate.opsForValue().get(USER_TOKEN_KEY + token);

        if (tokenObj == null) {
            log.warn("Redis用户信息为空token={}", token);
            byte[] bits = JSONResult.failed(ResultCode.INVALID_TOKEN.getCode(), ResultCode.INVALID_TOKEN.getValue());
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            throw new BusinessException(Mono.just(buffer));
        }

        Token tk = (Token) tokenObj;
        if (StringUtils.isEmpty(tk.getSubjectId()) | StringUtils.isEmpty(tk.getSubjectClass())) {
            log.warn("Redis用户信息为空token={}", token);
            byte[] bits = JSONResult.failed(ResultCode.INVALID_TOKEN.getCode(), ResultCode.INVALID_TOKEN.getValue());
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            throw new BusinessException(Mono.just(buffer));
        }
//        verifyPermission(url, tk, response);
//        try {
//            verifyAuth(url,tk,token,response);
//        }catch (BusinessException e){
//            throw e;
//        }
        return tk;

    }

    /**
     * 权限校验
     *
     * @param url
     * @param tk
     * @param token
     * @param response
     */
    public void verifyAuth(String url, Token tk, String token, ServerHttpResponse response) throws BusinessException {
        //        //获取每个Url所对应的权限控制符
        String urlAuth = getUrlAuth(url);
        //无需校验 放过
        if (ANNO.equals(urlAuth)) {

        } else if (AUTHC.equals(urlAuth)) {  //用户登录后可以访问


        } else {  //权限校验
            if (ROLES.equals(urlAuth)) {
                JSONArray rolePermission = getUrlRolePermission(url);
                if (!rolePermission.contains(tk.getSubjectClass())) {
                    JSONArray permissions = getUrlPermission(url);
                    JSONArray userPermission = getUserPermission(token, url);
                    if (!permissions.equals(userPermission)) {
                        log.warn("用户无权限 ");
                        byte[] bits = JSONResult.failed(ResultCode.NOT_PERMISSION.getCode(), ResultCode.NOT_PERMISSION.getValue());
                        DataBuffer buffer = response.bufferFactory().wrap(bits);
                        throw new BusinessException(Mono.just(buffer));
                    }
                }
            }

        }
    }

    /**
     * 获取用户权限
     *
     * @param token
     * @return
     */
    public JSONArray getUserPermission(String token, String url) {
        Object obj = redisTemplate.opsForHash().get(String.format(URL_USER_PERMISSION_KEY, token), url);
        JSONArray jsonArray = JSONArray.parseArray(obj.toString());
        if (obj != null) {
            return jsonArray;
        }
        return null;
    }

    /**
     * 获取认证标识 判断是否需要 权限校验
     *
     * @param url
     * @return
     */
    public String getUrlAuth(String url) {
        String urlRep = urlReplace(url);
        Object obj = redisTemplate.opsForValue().get(String.format(URL_AUTH_KEY, url));
        if (obj == null) {
            obj = redisTemplate.opsForValue().get(String.format(URL_AUTH_KEY, urlRep));
        }
        if (obj != null) {
            return obj.toString();
        }
        return null;
    }

    /**
     * 获取权限标识
     *
     * @param url
     * @return
     */
    public JSONArray getUrlPermission(String url) {
        String urlRep = urlReplace(url);
        Object obj = redisTemplate.opsForValue().get(String.format(URL_PERMISSION_KEY, url));
        if (obj == null) {
            obj = redisTemplate.opsForValue().get(String.format(URL_PERMISSION_KEY, urlRep));
        }
        JSONArray jsonArray = JSONArray.parseArray(obj.toString());
        if (obj != null) {
            return jsonArray;
        }
        return null;
    }

    /**
     * 获取权限标识
     *
     * @param url
     * @return
     */
    public JSONArray getUrlRolePermission(String url) {
//        JSONArray list = new JSONArray();
//        redisTemplate.opsForHash().put(String.format(URL_PERMISSION_KEY,url),role,list.toJSONString());
        String urlRep = urlReplace(url);
        Object obj = redisTemplate.opsForValue().get(String.format(URL_ROLE_KEY, url));
        if (obj == null) {
            obj = redisTemplate.opsForValue().get(String.format(URL_ROLE_KEY, urlRep));
        }
        JSONArray jsonArray = JSONArray.parseArray(obj.toString());
        if (obj != null) {
            return jsonArray;
        }
        return null;
    }

    /**
     * 请求头校验
     *
     * @param response
     * @param request
     * @param token
     * @param sign
     * @param timestamp
     * @param rawPath
     * @param bodyStr
     * @param equipmentType
     * @param version
     * @return
     * @throws BusinessException
     */
    @Override
    public Boolean headersVerification(ServerHttpResponse response, ServerHttpRequest request, String token, String sign, String timestamp, String rawPath, String bodyStr, String equipmentType, String version) throws BusinessException {
//        if ((StringUtils.isEmpty(token) || StringUtils.isEmpty(timestamp)) && (!rawPath.contains("client/common/login"))) {
        if (StringUtils.isEmpty(token) && !rawPath.contains("client/common/login")
                && !rawPath.contains("client/common/sendVerificationCode")
                && !rawPath.contains("client/identityRegister/register")

        ) {
            log.warn("Token={}为空", token, timestamp);
            byte[] bits = JSONResult.failed(ResultCode.LACK_TOKEN.getCode(), ResultCode.LACK_TOKEN.getValue());
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            throw new BusinessException(Mono.just(buffer));
        }
        if ((StringUtils.isEmpty(timestamp))) {
            log.warn(" timestamp={} 为空", token, timestamp);
            byte[] bits = JSONResult.failed(ResultCode.LACK_TIMESTAMP.getCode(), ResultCode.LACK_TIMESTAMP.getValue());
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            throw new BusinessException(Mono.just(buffer));
        }
        // 校验timestamp和当前时间的差值是否在30分钟内
        if (timestamp != "2147483647") {
            Long time = System.currentTimeMillis() - Long.parseLong(timestamp);
            if (Math.abs(time) > 30 * 60 * 1000) {
                log.warn(" 校验timestamp和当前时间的差值是否在30分钟内 token={} ,time={} ", token, time);
                byte[] bits = JSONResult.failed(ResultCode.INVALID_TIMESTAMP.getCode(), ResultCode.INVALID_TIMESTAMP.getValue());
                DataBuffer buffer = response.bufferFactory().wrap(bits);
                throw new BusinessException(Mono.just(buffer));
            }
        }
//        client/ucloud/uploadFileToUcloudAndShow
        if ((StringUtils.isEmpty(sign)) && !rawPath.contains("client/ucloud/uploadFileToUcloudAndShow")
        ) {
            log.warn(" sign  token={} 为空", token);
            byte[] bits = JSONResult.failed(ResultCode.LACK_SIGN.getCode(), ResultCode.LACK_SIGN.getValue());
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            throw new BusinessException(Mono.just(buffer));
        }
        if (StringUtils.isNotEmpty(bodyStr)
                && !rawPath.contains("client/ucloud/uploadFileToUcloudAndShow")
                && !verifySign(bodyStr, sign, timestamp, equipmentType, version)
        ) {
//            return processResult(ResultCode.INVALID_SIGN, action);
            log.warn(" 签名校验失败 bodyStr={} sign={}", bodyStr, sign);
            byte[] bits = JSONResult.failed(ResultCode.INVALID_SIGN.getCode(), ResultCode.INVALID_SIGN.getValue());
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            throw new BusinessException(Mono.just(buffer));
        }


        //ip拦截
        if (!active.equals("dev") && ipInterceptor.isIllegalByIp(request)) {
            log.warn("IP拦截请求失败");
            byte[] bits = JSONResult.failed("非法访问");
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            throw new BusinessException(Mono.just(buffer));
        }

        return true;
    }

    @Override
    public String getLoginUser(String token, ServerHttpResponse response) {

        Object loginUserObj = redisTemplate.opsForValue().get(USER_TOKEN_LOGIN_INFO_KEY + token);
        if (ObjectUtils.isEmpty(loginUserObj)) {
            log.warn("当前登录用户信息不存在={}", token);
            byte[] bits = JSONResult.failed(ResultCode.INVALID_TOKEN.getCode(), ResultCode.INVALID_TOKEN.getValue());
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            throw new BusinessException(Mono.just(buffer));
        }
        return JSONObject.toJSONString(loginUserObj);
    }

    @Override
    public Boolean verifyPermission(String url, Token token, ServerHttpResponse response) {
        //用户 登录ID
        String identityId = token.getSubjectId();
        //用户 登录身份
        String identityType = token.getSubjectClass();
        Object rUserRoleList = redis.opsForHash().get(AuthEnums.AUTH_USER_ROLE.getCode(), identityId);
        if (rUserRoleList == null) {
            return true;
        }
        List<String> userRoleList = new ArrayList<>();
        if (rUserRoleList instanceof List) {
            userRoleList = (List<String>) rUserRoleList;
        }

        //查询缓存中的 path
//        val rPaths = redis.opsForHash<String,Any>().get(AuthEnums.AUTH_MENU_PATH.code, menu.url)
        Object rUrl = redis.opsForHash().get(AuthEnums.AUTH_MENU_URL_PATH.getCode(), url);
        if (rUrl == null) {

            log.info("当前地址默认/**放开，未配置接口不做权限要求");
            return true;
        }
        Object rUrlType = redis.opsForHash().get(AuthEnums.AUTH_URL_TYPE.getCode(), rUrl.toString());
        if (rUrlType == null) {

            log.info("当前地址默认/**放开，未配置接口不做权限要求");
            return true;
        }
//        if (rUrlType==null){
//            log.warn("当前地址无权限={}", token);
//            byte[] bits = JSONResult.failed(ResultCode.NOT_PERMISSION.getCode(), ResultCode.NOT_PERMISSION.getValue());
//            DataBuffer buffer = response.bufferFactory().wrap(bits);
//            throw new BusinessException(Mono.just(buffer));
//        }
        //当前为权限URL
        if (rUrlType != null && rUrlType.equals(AuthEnums.AUTH_URL_TYPE_PERMISSION.getCode())) {

            Object robj = redis.opsForHash().get(AuthEnums.AUTH_PERMISSION_ROLES.getCode(), rUrl.toString());
            if (ObjectUtils.isNotEmpty(robj)) {
                if (robj instanceof List) {
                    List<String> rolesList = (List<String>) robj;
                    boolean flag = false;
                    for (String roleCode : userRoleList) {
                        if (rolesList.contains(roleCode)) {
                            flag = true;
                            break;
                        }
                    }
                    if (!flag) {
                        log.warn("当前用户无权限={}", token);
                        byte[] bits = JSONResult.failed(ResultCode.NOT_PERMISSION.getCode(), ResultCode.NOT_PERMISSION.getValue());
                        DataBuffer buffer = response.bufferFactory().wrap(bits);
                        throw new BusinessException(Mono.just(buffer));
                    }
                }
            }
        }


        //当前为 菜单URL
        if (rUrlType != null && rUrlType.equals(AuthEnums.AUTH_URL_TYPE_MENU.getCode())) {
            //根据菜单Url 获取真实 path地址
//            Object rMenuPath = redis.opsForHash().get(AuthEnums.AUTH_MENU_PATH.getCode(), rUrl.toString());
//            if (rMenuPath != null) {
                Object robj = redis.opsForHash().get(AuthEnums.AUTH_MENU_ROLES.getCode(),  rUrl.toString());
                if (ObjectUtils.isNotEmpty(robj)) {
                    if (robj instanceof List) {
                        List<String> rolesList = (List<String>) robj;
                        boolean flag = false;
                        for (String roleCode : userRoleList) {
                            if (rolesList.contains(roleCode)) {
                                flag = true;
                                break;
                            }
                        }
                        if (!flag) {
                            log.warn("当前用户无权限={}", token);
                            byte[] bits = JSONResult.failed(ResultCode.NOT_PERMISSION.getCode(), ResultCode.NOT_PERMISSION.getValue());
                            DataBuffer buffer = response.bufferFactory().wrap(bits);
                            throw new BusinessException(Mono.just(buffer));
                        }
                    }
//                }
            }

        }


        return true;
    }


    /**
     * 签名校验
     *
     * @param signData
     * @param timestamp
     * @param equipmentType
     * @param version
     * @return
     */
    private static boolean verifySign(String bodyStr, String signData, String timestamp, String equipmentType, String version) {
        // 去掉参数中的空值、sign等参数
//        Map<String, String> filteredParameterMap = new HashMap<>();
        log.info("签名 原数据={}", bodyStr.trim());
        Map<String, Object> jsonObject = JSONObject.parseObject(bodyStr, LinkedHashMap.class, Feature.OrderedField);
        Map<String, Object> hutoolJSON = JSONUtil.parseObj(bodyStr, false, true);
//        log.info("数据转化stringToMap后数据={}", stringToMap);
        log.info("数据转化Map后数据={}", jsonObject);
        log.info("数据转化hutoolJSON后数据={}", hutoolJSON);
        jsonObject.remove("timestamp");
        jsonObject.put("timestamp", timestamp);
        hutoolJSON.remove("timestamp");
        hutoolJSON.put("timestamp", timestamp);
        Set<String> keys = jsonObject.keySet();
        List<String> list = new LinkedList<>();
        for (String key : keys) {
            list.add(key);
        }
        Collections.sort(list);
        StringBuffer stringBuffer = new StringBuffer();
        String currentVersion = version.replace(".", "").trim();
        if ("Android".equals(equipmentType) && Integer.valueOf(currentVersion) < 959) {
            return true;
        }

        for (String key : list) {

            if ("Android".equals(equipmentType) && ObjectUtils.isNotEmpty(jsonObject.get(key)) && !"token".equals(key) && !"sign".equals(key)) {
                if (stringBuffer.length() > 0) {
                    stringBuffer.append("&");
                }

                stringBuffer.append(key);
                stringBuffer.append("=");
                stringBuffer.append(jsonObject.get(key));

            } else if (ObjectUtils.isNotEmpty(jsonObject.get(key)) && !"token".equals(key) && !"sign".equals(key)) {


                if ("PC".equals(equipmentType)) {
                    if (stringBuffer.length() > 0) {
                        stringBuffer.append("&");
                    }
                    if (StringUtils.isNotEmpty(key)) {
                        stringBuffer.append(key);
                        stringBuffer.append("=");
                        stringBuffer.append(hutoolJSON.get(key).toString());
                    }
                } else if ("IOS".equals(equipmentType)) {
                    if (StringUtils.isEmpty(currentVersion) || Integer.valueOf(currentVersion) < 153) {
                        return true;
                    }
                    if (StringUtils.isNotEmpty(key)) {
                        if (!(hutoolJSON.get(key) instanceof List)) {
                            if (stringBuffer.length() > 0) {
                                stringBuffer.append("&");
                            }
                            stringBuffer.append(key);
                            stringBuffer.append("=");
                            stringBuffer.append(hutoolJSON.get(key));
                        }
                    }
                } else {
                    if (stringBuffer.length() > 0) {
                        stringBuffer.append("&");
                    }
                    stringBuffer.append(key);
                    stringBuffer.append("=");
                    stringBuffer.append(jsonObject.get(key).toString());
                }
//                stringBuffer.append(jsonObject.get(key).toString());


            }

        }
        stringBuffer.append("&salt=");
        stringBuffer.append(signSalt);
        String linkString = stringBuffer.toString();
        log.info("签名前数据={}", linkString);
        String sign = Md5Util.md5(linkString);
        log.info("签名={}", sign);
        return sign.equals(signData);
    }

    /**
     * 获取请求体中的字符串内容
     *
     * @param serverHttpRequest
     * @return
     */
    private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {

        Flux<DataBuffer> body = serverHttpRequest.getBody();
        AtomicReference<String> bodyRef = new AtomicReference<>();
        // 缓存读取的request body信息
        body.subscribe(dataBuffer -> {
            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(dataBuffer.asByteBuffer());
            DataBufferUtils.release(dataBuffer);

            log.info("ccccc= {}", charBuffer.toString());
            bodyRef.set(charBuffer.toString());
        });
        //获取request body
        return bodyRef.get();

    }

    /**
     * 替换URL
     *
     * @param url
     * @return
     */
    public String urlReplace(String url) {
        String[] urlSplit = url.split("/");
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < urlSplit.length - 1; i++) {
            if (stringBuffer.length() > 0) {
                stringBuffer.append("/");
            }
            stringBuffer.append(urlSplit[i]);
        }
        stringBuffer.append("/**");
        url = stringBuffer.toString();
        return url;
    }


    public static void main(String[] args) {

        String a = "cartOrder=false&platform=IOS&timestamp=1632453831554&salt=microservices";
        String b = "cartOrder=false&&platform=IOS&timestamp=1632453831554&salt=microservices";
        String ab = "{\"timestamp\":\"121212\"}";
//        Map<String, Object> hutoolJSON = JSONUtil.parseObj(ab,false,true);
//        JSONObject abb = JSONObject.parseObject(ab);
//        System.out.println(hutoolJSON);
//        System.out.println(abb);

        verifySign(ab, "7EFD09D5D79FD662ECADD89F30698BEC", "1631864843101", "PC", "1.2");
        //        Collections.sort();
        //        Set<String> keys =  parameterMap.keySet();
//        List<String> list = keys.stream().collect(Collectors.toList());

//
////       cartOrder=true&placeOrderList=&platform=IOS&timestamp=1629113658756&salt=microservices
//        // 去掉参数中的空值、sign等参数
//        Map<String,String> parameterMap = new LinkedHashMap<>();
//        List<Map<String,Object>> ary = new ArrayList<>();
//        Map<String,Object> jsonObject = new LinkedHashMap<>();
//        jsonObject.put("dem.designId","40288a8a7b4c957d017b4ca61b6b0b33");
//
//        jsonObject.put("dem.designDetailId","40288a8a7b4c957e017b4ca6af2c1fa7");
//        Map<String,Object> basicSizeRange =  new LinkedHashMap<>();
//        basicSizeRange.put("dem.size","123");
//
//        basicSizeRange.put("dem.basicSizeRangeId","40288a8b78b434460178b4b50620003e");
//        jsonObject.put("dem.basicSizeRange",basicSizeRange);
//
//        Map<String,Object> jsonObject2 = new LinkedHashMap<>();
//        jsonObject2.put("dem.designId","40288a8a7b4c957d017b4ca61b6b0b33");
//
//        jsonObject2.put("dem.designDetailId","40288a8a7b4c957e017b4ca6af2c1fa7");
//        Map<String,Object> basicSizeRange2 = new LinkedHashMap<>();
//        basicSizeRange2.put("dem.basicSizeRangeId","40288a8b78b434460178b4b50620003e");
//        basicSizeRange2.put("dem.size","123");
//        jsonObject2.put("dem.basicSizeRange",basicSizeRange2);
//        ary.add(jsonObject);
//        ary.add(jsonObject2);
//        parameterMap.put("dem.placeOrderList",ary.toString());
//        parameterMap.put("dem.timestamp","1629114820724");
//        parameterMap.put("dem.platform","IOS");
//        parameterMap.put("dem.cartOrder","true");
//
//        Set<String> keys =  parameterMap.keySet();
//        List<String> list = keys.stream().collect(Collectors.toList());
//
//        Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
//        StringBuffer stringBuffer = new StringBuffer();
//        for (String key : list) {
//            if (stringBuffer.length()>0){
//                stringBuffer.append("&");
//            }
//            stringBuffer.append(key);
//            stringBuffer.append("=");
//            stringBuffer.append(parameterMap.get(key));
//        }
//        stringBuffer.append("&salt=");
//        stringBuffer.append(signSalt);
//        String linkString = stringBuffer.toString();
//        String sign = Md5Util.md5(linkString);
//        System.out.println(linkString);
//        System.out.println(sign);
//
//     String c = "designList=[{\"designId\":\"40288a8a7b4c957d017b4ca614665311\",\"colorDtoList\":[{\"sizeName\":\"9942151060d635159b7bf4d41049b2cf\",\"sizeCountDtoList\":[{\"count\":\"555\",\"sizeCountId\":\"9942151060d635159b7bf4d41049b2cf\",\"sizeName\":\"XXL\"}],\"price\":\"94.5\",\"itemCode\":\"9918212\",\"designDetailId\":\"40288a8a7b4c957d017b4ca64455633a\",\"futureIndentDetailId\":\"4434e995d647038b6c8fb66d674510a7\",\"deliveryDate\":\"2021-08-24\"}]}]&futureIndentId=bdae25c4be71e12ef8276c8c07466543&identityAddressId=2c91808c7b4eaa49017b4f3f0786007b&timestamp=1629130023492&salt=microservices";
//     String d = "designList=[{\"designId\":\"40288a8a7b4c957d017b4ca614665311\",\"colorDtoList\":[{\"sizeName\":\"9942151060d635159b7bf4d41049b2cf\",\"sizeCountDtoList\":[{\"count\":\"555\",\"sizeName\":\"XXL\",\"sizeCountId\":\"9942151060d635159b7bf4d41049b2cf\"}],\"price\":\"94.5\",\"itemCode\":\"9918212\",\"designDetailId\":\"40288a8a7b4c957d017b4ca64455633a\",\"futureIndentDetailId\":\"4434e995d647038b6c8fb66d674510a7\",\"deliveryDate\":\"2021-08-24\"}]}]&futureIndentId=bdae25c4be71e12ef8276c8c07466543&identityAddressId=2c91808c7b4eaa49017b4f3f0786007b&timestamp=1629130023492&salt=microservices";
//        System.out.println(c.equals(d));
    }

}
